{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "tags": [
     "pdf-title"
    ]
   },
   "source": [
    "# Batch Normalization\n",
    "One way to make deep networks easier to train is to use more sophisticated optimization procedures such as SGD+momentum, RMSProp, or Adam. Another strategy is to change the architecture of the network to make it easier to train. \n",
    "One idea along these lines is batch normalization which was proposed by [1] in 2015.\n",
    "\n",
    "The idea is relatively straightforward. Machine learning methods tend to work better when their input data consists of uncorrelated features with zero mean and unit variance. When training a neural network, we can preprocess the data before feeding it to the network to explicitly decorrelate its features; this will ensure that the first layer of the network sees data that follows a nice distribution. However, even if we preprocess the input data, the activations at deeper layers of the network will likely no longer be decorrelated and will no longer have zero mean or unit variance since they are output from earlier layers in the network. Even worse, during the training process the distribution of features at each layer of the network will shift as the weights of each layer are updated.\n",
    "\n",
    "The authors of [1] hypothesize that the shifting distribution of features inside deep neural networks may make training deep networks more difficult. To overcome this problem, [1] proposes to insert batch normalization layers into the network. At training time, a batch normalization layer uses a minibatch of data to estimate the mean and standard deviation of each feature. These estimated means and standard deviations are then used to center and normalize the features of the minibatch. A running average of these means and standard deviations is kept during training, and at test time these running averages are used to center and normalize features.\n",
    "\n",
    "It is possible that this normalization strategy could reduce the representational power of the network, since it may sometimes be optimal for certain layers to have features that are not zero-mean or unit variance. To this end, the batch normalization layer includes learnable shift and scale parameters for each feature dimension.\n",
    "\n",
    "[1] [Sergey Ioffe and Christian Szegedy, \"Batch Normalization: Accelerating Deep Network Training by Reducing\n",
    "Internal Covariate Shift\", ICML 2015.](https://arxiv.org/abs/1502.03167)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "tags": [
     "pdf-ignore"
    ]
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "=========== You can safely ignore the message below if you are NOT working on ConvolutionalNetworks.ipynb ===========\n",
      "\tYou will need to compile a Cython extension for a portion of this assignment.\n",
      "\tThe instructions to do this will be given in a section of the notebook below.\n",
      "\tThere will be an option for Colab users and another for Jupyter (local) users.\n"
     ]
    }
   ],
   "source": [
    "# As usual, a bit of setup\n",
    "import time\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "from cs231n.classifiers.fc_net import *\n",
    "from cs231n.data_utils import get_CIFAR10_data\n",
    "from cs231n.gradient_check import eval_numerical_gradient, eval_numerical_gradient_array\n",
    "from cs231n.solver import Solver\n",
    "\n",
    "%matplotlib inline\n",
    "plt.rcParams['figure.figsize'] = (10.0, 8.0) # set default size of plots\n",
    "plt.rcParams['image.interpolation'] = 'nearest'\n",
    "plt.rcParams['image.cmap'] = 'gray'\n",
    "\n",
    "# for auto-reloading external modules\n",
    "# see http://stackoverflow.com/questions/1907993/autoreload-of-modules-in-ipython\n",
    "%load_ext autoreload\n",
    "%autoreload 2\n",
    "\n",
    "def rel_error(x, y):\n",
    "    \"\"\" returns relative error \"\"\"\n",
    "    return np.max(np.abs(x - y) / (np.maximum(1e-8, np.abs(x) + np.abs(y))))\n",
    "\n",
    "def print_mean_std(x,axis=0):\n",
    "    print('  means: ', x.mean(axis=axis))\n",
    "    print('  stds:  ', x.std(axis=axis))\n",
    "    print() "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "tags": [
     "pdf-ignore"
    ]
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "X_train:  (49000, 3, 32, 32)\n",
      "y_train:  (49000,)\n",
      "X_val:  (1000, 3, 32, 32)\n",
      "y_val:  (1000,)\n",
      "X_test:  (1000, 3, 32, 32)\n",
      "y_test:  (1000,)\n"
     ]
    }
   ],
   "source": [
    "# Load the (preprocessed) CIFAR10 data.\n",
    "data = get_CIFAR10_data()\n",
    "for k, v in data.items():\n",
    "  print('%s: ' % k, v.shape)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Batch normalization: forward\n",
    "In the file `cs231n/layers.py`, implement the batch normalization forward pass in the function `batchnorm_forward`. Once you have done so, run the following to test your implementation.\n",
    "\n",
    "Referencing the paper linked to above in [1] may be helpful!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Before batch normalization:\n",
      "  means:  [ -2.3814598  -13.18038246   1.91780462]\n",
      "  stds:   [27.18502186 34.21455511 37.68611762]\n",
      "\n",
      "After batch normalization (gamma=1, beta=0)\n",
      "  means:  [5.32907052e-17 7.04991621e-17 4.22578639e-17]\n",
      "  stds:   [0.99999999 1.         1.        ]\n",
      "\n",
      "After batch normalization (gamma= [1. 2. 3.] , beta= [11. 12. 13.] )\n",
      "  means:  [11. 12. 13.]\n",
      "  stds:   [0.99999999 1.99999999 2.99999999]\n",
      "\n"
     ]
    }
   ],
   "source": [
    "# Check the training-time forward pass by checking means and variances\n",
    "# of features both before and after batch normalization   \n",
    "\n",
    "# Simulate the forward pass for a two-layer network\n",
    "np.random.seed(231)\n",
    "N, D1, D2, D3 = 200, 50, 60, 3\n",
    "X = np.random.randn(N, D1)\n",
    "W1 = np.random.randn(D1, D2)\n",
    "W2 = np.random.randn(D2, D3)\n",
    "a = np.maximum(0, X.dot(W1)).dot(W2)\n",
    "\n",
    "print('Before batch normalization:')\n",
    "print_mean_std(a,axis=0)\n",
    "\n",
    "gamma = np.ones((D3,))\n",
    "beta = np.zeros((D3,))\n",
    "# Means should be close to zero and stds close to one\n",
    "print('After batch normalization (gamma=1, beta=0)')\n",
    "a_norm, _ = batchnorm_forward(a, gamma, beta, {'mode': 'train'})\n",
    "print_mean_std(a_norm,axis=0)\n",
    "\n",
    "gamma = np.asarray([1.0, 2.0, 3.0])\n",
    "beta = np.asarray([11.0, 12.0, 13.0])\n",
    "# Now means should be close to beta and stds close to gamma\n",
    "print('After batch normalization (gamma=', gamma, ', beta=', beta, ')')\n",
    "a_norm, _ = batchnorm_forward(a, gamma, beta, {'mode': 'train'})\n",
    "print_mean_std(a_norm,axis=0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "After batch normalization (test-time):\n",
      "  means:  [-0.03927354 -0.04349152 -0.10452688]\n",
      "  stds:   [1.01531428 1.01238373 0.97819988]\n",
      "\n"
     ]
    }
   ],
   "source": [
    "# Check the test-time forward pass by running the training-time\n",
    "# forward pass many times to warm up the running averages, and then\n",
    "# checking the means and variances of activations after a test-time\n",
    "# forward pass.\n",
    "\n",
    "np.random.seed(231)\n",
    "N, D1, D2, D3 = 200, 50, 60, 3\n",
    "W1 = np.random.randn(D1, D2)\n",
    "W2 = np.random.randn(D2, D3)\n",
    "\n",
    "bn_param = {'mode': 'train'}\n",
    "gamma = np.ones(D3)\n",
    "beta = np.zeros(D3)\n",
    "\n",
    "for t in range(50):\n",
    "  X = np.random.randn(N, D1)\n",
    "  a = np.maximum(0, X.dot(W1)).dot(W2)\n",
    "  batchnorm_forward(a, gamma, beta, bn_param)\n",
    "\n",
    "bn_param['mode'] = 'test'\n",
    "X = np.random.randn(N, D1)\n",
    "a = np.maximum(0, X.dot(W1)).dot(W2)\n",
    "a_norm, _ = batchnorm_forward(a, gamma, beta, bn_param)\n",
    "\n",
    "# Means should be close to zero and stds close to one, but will be\n",
    "# noisier than training-time forward passes.\n",
    "print('After batch normalization (test-time):')\n",
    "print_mean_std(a_norm,axis=0)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Batch normalization: backward\n",
    "Now implement the backward pass for batch normalization in the function `batchnorm_backward`.\n",
    "\n",
    "To derive the backward pass you should write out the computation graph for batch normalization and backprop through each of the intermediate nodes. Some intermediates may have multiple outgoing branches; make sure to sum gradients across these branches in the backward pass.\n",
    "\n",
    "Once you have finished, run the following to numerically check your backward pass."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "dx error:  1.7029258328157158e-09\n",
      "dgamma error:  7.420414216247087e-13\n",
      "dbeta error:  2.8795057655839487e-12\n"
     ]
    }
   ],
   "source": [
    "# Gradient check batchnorm backward pass\n",
    "np.random.seed(231)\n",
    "N, D = 4, 5\n",
    "x = 5 * np.random.randn(N, D) + 12\n",
    "gamma = np.random.randn(D)\n",
    "beta = np.random.randn(D)\n",
    "dout = np.random.randn(N, D)\n",
    "\n",
    "bn_param = {'mode': 'train'}\n",
    "fx = lambda x: batchnorm_forward(x, gamma, beta, bn_param)[0]\n",
    "fg = lambda a: batchnorm_forward(x, a, beta, bn_param)[0]\n",
    "fb = lambda b: batchnorm_forward(x, gamma, b, bn_param)[0]\n",
    "\n",
    "dx_num = eval_numerical_gradient_array(fx, x, dout)\n",
    "da_num = eval_numerical_gradient_array(fg, gamma.copy(), dout)\n",
    "db_num = eval_numerical_gradient_array(fb, beta.copy(), dout)\n",
    "\n",
    "_, cache = batchnorm_forward(x, gamma, beta, bn_param)\n",
    "dx, dgamma, dbeta = batchnorm_backward(dout, cache)\n",
    "#You should expect to see relative errors between 1e-13 and 1e-8\n",
    "print('dx error: ', rel_error(dx_num, dx))\n",
    "print('dgamma error: ', rel_error(da_num, dgamma))\n",
    "print('dbeta error: ', rel_error(db_num, dbeta))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Batch normalization: alternative backward\n",
    "In class we talked about two different implementations for the sigmoid backward pass. One strategy is to write out a computation graph composed of simple operations and backprop through all intermediate values. Another strategy is to work out the derivatives on paper. For example, you can derive a very simple formula for the sigmoid function's backward pass by simplifying gradients on paper.\n",
    "\n",
    "Surprisingly, it turns out that you can do a similar simplification for the batch normalization backward pass too!  \n",
    "\n",
    "In the forward pass, given a set of inputs $X=\\begin{bmatrix}x_1\\\\x_2\\\\...\\\\x_N\\end{bmatrix}$, \n",
    "\n",
    "we first calculate the mean $\\mu$ and variance $v$.\n",
    "With $\\mu$ and $v$ calculated, we can calculate the standard deviation $\\sigma$  and normalized data $Y$.\n",
    "The equations and graph illustration below describe the computation ($y_i$ is the i-th element of the vector $Y$).\n",
    "\n",
    "\\begin{align}\n",
    "& \\mu=\\frac{1}{N}\\sum_{k=1}^N x_k  &  v=\\frac{1}{N}\\sum_{k=1}^N (x_k-\\mu)^2 \\\\\n",
    "& \\sigma=\\sqrt{v+\\epsilon}         &  y_i=\\frac{x_i-\\mu}{\\sigma}\n",
    "\\end{align}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<img src=\"https://raw.githubusercontent.com/cs231n/cs231n.github.io/master/assets/a2/batchnorm_graph.png\">"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "tags": [
     "pdf-ignore"
    ]
   },
   "source": [
    "The meat of our problem during backpropagation is to compute $\\frac{\\partial L}{\\partial X}$, given the upstream gradient we receive, $\\frac{\\partial L}{\\partial Y}.$ To do this, recall the chain rule in calculus gives us $\\frac{\\partial L}{\\partial X} = \\frac{\\partial L}{\\partial Y} \\cdot \\frac{\\partial Y}{\\partial X}$.\n",
    "\n",
    "The unknown/hart part is $\\frac{\\partial Y}{\\partial X}$. We can find this by first deriving step-by-step our local gradients at \n",
    "$\\frac{\\partial v}{\\partial X}$, $\\frac{\\partial \\mu}{\\partial X}$,\n",
    "$\\frac{\\partial \\sigma}{\\partial v}$, \n",
    "$\\frac{\\partial Y}{\\partial \\sigma}$, and $\\frac{\\partial Y}{\\partial \\mu}$,\n",
    "and then use the chain rule to compose these gradients (which appear in the form of vectors!) appropriately to compute $\\frac{\\partial Y}{\\partial X}$.\n",
    "\n",
    "If it's challenging to directly reason about the gradients over $X$ and $Y$ which require matrix multiplication, try reasoning about the gradients in terms of individual elements $x_i$ and $y_i$ first: in that case, you will need to come up with the derivations for $\\frac{\\partial L}{\\partial x_i}$, by relying on the Chain Rule to first calculate the intermediate $\\frac{\\partial \\mu}{\\partial x_i}, \\frac{\\partial v}{\\partial x_i}, \\frac{\\partial \\sigma}{\\partial x_i},$ then assemble these pieces to calculate $\\frac{\\partial y_i}{\\partial x_i}$. \n",
    "\n",
    "You should make sure each of the intermediary gradient derivations are all as simplified as possible, for ease of implementation. \n",
    "\n",
    "After doing so, implement the simplified batch normalization backward pass in the function `batchnorm_backward_alt` and compare the two implementations by running the following. Your two implementations should compute nearly identical results, but the alternative implementation should be a bit faster."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "dx difference:  0.0\n",
      "dgamma difference:  0.0\n",
      "dbeta difference:  0.0\n",
      "speedup: 3.00x\n"
     ]
    }
   ],
   "source": [
    "np.random.seed(231)\n",
    "N, D = 100, 500\n",
    "x = 5 * np.random.randn(N, D) + 12\n",
    "gamma = np.random.randn(D)\n",
    "beta = np.random.randn(D)\n",
    "dout = np.random.randn(N, D)\n",
    "\n",
    "bn_param = {'mode': 'train'}\n",
    "out, cache = batchnorm_forward(x, gamma, beta, bn_param)\n",
    "\n",
    "t1 = time.time()\n",
    "dx1, dgamma1, dbeta1 = batchnorm_backward(dout, cache)\n",
    "t2 = time.time()\n",
    "dx2, dgamma2, dbeta2 = batchnorm_backward_alt(dout, cache)\n",
    "t3 = time.time()\n",
    "\n",
    "print('dx difference: ', rel_error(dx1, dx2))\n",
    "print('dgamma difference: ', rel_error(dgamma1, dgamma2))\n",
    "print('dbeta difference: ', rel_error(dbeta1, dbeta2))\n",
    "print('speedup: %.2fx' % ((t2 - t1) / (t3 - t2)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Fully Connected Nets with Batch Normalization\n",
    "Now that you have a working implementation for batch normalization, go back to your `FullyConnectedNet` in the file `cs231n/classifiers/fc_net.py`. Modify your implementation to add batch normalization.\n",
    "\n",
    "Concretely, when the `normalization` flag is set to `\"batchnorm\"` in the constructor, you should insert a batch normalization layer before each ReLU nonlinearity. The outputs from the last layer of the network should not be normalized. Once you are done, run the following to gradient-check your implementation.\n",
    "\n",
    "HINT: You might find it useful to define an additional helper layer similar to those in the file `cs231n/layer_utils.py`. If you decide to do so, do it in the file `cs231n/classifiers/fc_net.py`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Running check with reg =  0\n",
      "Initial loss:  2.2611955101340957\n",
      "W1 relative error: 1.10e-04\n",
      "W2 relative error: 2.85e-06\n",
      "W3 relative error: 3.92e-10\n",
      "b1 relative error: 5.55e-09\n",
      "b2 relative error: 2.22e-08\n",
      "b3 relative error: 4.78e-11\n",
      "beta1 relative error: 7.33e-09\n",
      "beta2 relative error: 1.89e-09\n",
      "gamma1 relative error: 7.57e-09\n",
      "gamma2 relative error: 1.96e-09\n",
      "\n",
      "Running check with reg =  3.14\n",
      "Initial loss:  6.996533220108303\n",
      "W1 relative error: 1.98e-06\n",
      "W2 relative error: 2.28e-06\n",
      "W3 relative error: 1.11e-08\n",
      "b1 relative error: 5.55e-09\n",
      "b2 relative error: 5.55e-09\n",
      "b3 relative error: 2.23e-10\n",
      "beta1 relative error: 6.65e-09\n",
      "beta2 relative error: 3.48e-09\n",
      "gamma1 relative error: 5.94e-09\n",
      "gamma2 relative error: 4.14e-09\n"
     ]
    }
   ],
   "source": [
    "np.random.seed(231)\n",
    "N, D, H1, H2, C = 2, 15, 20, 30, 10\n",
    "X = np.random.randn(N, D)\n",
    "y = np.random.randint(C, size=(N,))\n",
    "\n",
    "# You should expect losses between 1e-4~1e-10 for W, \n",
    "# losses between 1e-08~1e-10 for b,\n",
    "# and losses between 1e-08~1e-09 for beta and gammas.\n",
    "for reg in [0, 3.14]:\n",
    "  print('Running check with reg = ', reg)\n",
    "  model = FullyConnectedNet([H1, H2], input_dim=D, num_classes=C,\n",
    "                            reg=reg, weight_scale=5e-2, dtype=np.float64,\n",
    "                            normalization='batchnorm')\n",
    "\n",
    "  loss, grads = model.loss(X, y)\n",
    "  print('Initial loss: ', loss)\n",
    "\n",
    "  for name in sorted(grads):\n",
    "    f = lambda _: model.loss(X, y)[0]\n",
    "    grad_num = eval_numerical_gradient(f, model.params[name], verbose=False, h=1e-5)\n",
    "    print('%s relative error: %.2e' % (name, rel_error(grad_num, grads[name])))\n",
    "  if reg == 0: print()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Batchnorm for deep networks\n",
    "Run the following to train a six-layer network on a subset of 1000 training examples both with and without batch normalization."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Solver with batch norm:\n",
      "(Iteration 1 / 200) loss: 2.340974\n"
     ]
    },
    {
     "ename": "AttributeError",
     "evalue": "'NoneType' object has no attribute 'shape'",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mAttributeError\u001b[0m                            Traceback (most recent call last)",
      "\u001b[1;32m<ipython-input-8-9bb41d2d96db>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m\u001b[0m\n\u001b[0;32m     23\u001b[0m                 },\n\u001b[0;32m     24\u001b[0m                 verbose=True,print_every=20)\n\u001b[1;32m---> 25\u001b[1;33m \u001b[0mbn_solver\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mtrain\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m     26\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m     27\u001b[0m \u001b[0mprint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'\\nSolver without batch norm:'\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;32m~\\Desktop\\homework\\国创\\assignment2\\cs231n\\solver.py\u001b[0m in \u001b[0;36mtrain\u001b[1;34m(self)\u001b[0m\n\u001b[0;32m    283\u001b[0m             \u001b[0mlast_it\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mt\u001b[0m \u001b[1;33m==\u001b[0m \u001b[0mnum_iterations\u001b[0m \u001b[1;33m-\u001b[0m \u001b[1;36m1\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    284\u001b[0m             \u001b[1;32mif\u001b[0m \u001b[0mfirst_it\u001b[0m \u001b[1;32mor\u001b[0m \u001b[0mlast_it\u001b[0m \u001b[1;32mor\u001b[0m \u001b[0mepoch_end\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 285\u001b[1;33m                 train_acc = self.check_accuracy(\n\u001b[0m\u001b[0;32m    286\u001b[0m                     \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mX_train\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0my_train\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mnum_samples\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mnum_train_samples\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    287\u001b[0m                 )\n",
      "\u001b[1;32m~\\Desktop\\homework\\国创\\assignment2\\cs231n\\solver.py\u001b[0m in \u001b[0;36mcheck_accuracy\u001b[1;34m(self, X, y, num_samples, batch_size)\u001b[0m\n\u001b[0;32m    245\u001b[0m             \u001b[0mstart\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mi\u001b[0m \u001b[1;33m*\u001b[0m \u001b[0mbatch_size\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    246\u001b[0m             \u001b[0mend\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;33m(\u001b[0m\u001b[0mi\u001b[0m \u001b[1;33m+\u001b[0m \u001b[1;36m1\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;33m*\u001b[0m \u001b[0mbatch_size\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 247\u001b[1;33m             \u001b[0mscores\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mmodel\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mloss\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mX\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mstart\u001b[0m\u001b[1;33m:\u001b[0m\u001b[0mend\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m    248\u001b[0m             \u001b[0my_pred\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mnp\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0margmax\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mscores\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0maxis\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;36m1\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    249\u001b[0m         \u001b[0my_pred\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mnp\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mhstack\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0my_pred\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;32m~\\Desktop\\homework\\国创\\assignment2\\cs231n\\classifiers\\fc_net.py\u001b[0m in \u001b[0;36mloss\u001b[1;34m(self, X, y)\u001b[0m\n\u001b[0;32m    257\u001b[0m                     \u001b[0mgamma\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mparams\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;34m'gamma'\u001b[0m\u001b[1;33m+\u001b[0m\u001b[0mstrid\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    258\u001b[0m                     \u001b[0mbeta\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mparams\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;34m'beta'\u001b[0m\u001b[1;33m+\u001b[0m\u001b[0mstrid\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 259\u001b[1;33m                     \u001b[0mOutput\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mcache\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;34m'Cache'\u001b[0m \u001b[1;33m+\u001b[0m \u001b[0mstrid\u001b[0m\u001b[1;33m]\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0maffine_bn_relu_forward\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mInput\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mWi\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mbi\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mgamma\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mbeta\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mbn_params\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mi\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m    260\u001b[0m                 \u001b[1;32melif\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mnormalization\u001b[0m \u001b[1;33m==\u001b[0m \u001b[1;34m'layernorm'\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    261\u001b[0m                     \u001b[0mgamma\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mparams\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;34m'gamma'\u001b[0m\u001b[1;33m+\u001b[0m\u001b[0mstrid\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;32m~\\Desktop\\homework\\国创\\assignment2\\cs231n\\classifiers\\fc_net.py\u001b[0m in \u001b[0;36maffine_bn_relu_forward\u001b[1;34m(x, w, b, gamma, beta, bn_param)\u001b[0m\n\u001b[0;32m    324\u001b[0m \u001b[1;31m# affine + batch norm + relu的组合层前向\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    325\u001b[0m \u001b[1;32mdef\u001b[0m \u001b[0maffine_bn_relu_forward\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mx\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mw\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mb\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mgamma\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mbeta\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mbn_param\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 326\u001b[1;33m     \u001b[0ma\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mfc_cache\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0maffine_forward\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mx\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mw\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mb\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m    327\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    328\u001b[0m     \u001b[0mbn\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mbn_cache\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mbatchnorm_forward\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0ma\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mgamma\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mbeta\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mbn_param\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;32m~\\Desktop\\homework\\国创\\assignment2\\cs231n\\layers.py\u001b[0m in \u001b[0;36maffine_forward\u001b[1;34m(x, w, b)\u001b[0m\n\u001b[0;32m     24\u001b[0m     \u001b[1;31m###########################################################################\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m     25\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 26\u001b[1;33m     \u001b[0mN\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0mD\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mx\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mshape\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;36m0\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0mw\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mshape\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;36m0\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m     27\u001b[0m     \u001b[0mout\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mx\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mreshape\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mN\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0mD\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mdot\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mw\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;33m+\u001b[0m \u001b[0mb\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m     28\u001b[0m     \u001b[1;31m###########################################################################\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;31mAttributeError\u001b[0m: 'NoneType' object has no attribute 'shape'"
     ]
    }
   ],
   "source": [
    "np.random.seed(231)\n",
    "# Try training a very deep net with batchnorm\n",
    "hidden_dims = [100, 100, 100, 100, 100]\n",
    "\n",
    "num_train = 1000\n",
    "small_data = {\n",
    "  'X_train': data['X_train'][:num_train],\n",
    "  'y_train': data['y_train'][:num_train],\n",
    "  'X_val': data['X_val'],\n",
    "  'y_val': data['y_val'],\n",
    "}\n",
    "\n",
    "weight_scale = 2e-2\n",
    "bn_model = FullyConnectedNet(hidden_dims, weight_scale=weight_scale, normalization='batchnorm')\n",
    "model = FullyConnectedNet(hidden_dims, weight_scale=weight_scale, normalization=None)\n",
    "\n",
    "print('Solver with batch norm:')\n",
    "bn_solver = Solver(bn_model, small_data,\n",
    "                num_epochs=10, batch_size=50,\n",
    "                update_rule='adam',\n",
    "                optim_config={\n",
    "                  'learning_rate': 1e-3,\n",
    "                },\n",
    "                verbose=True,print_every=20)\n",
    "bn_solver.train()\n",
    "\n",
    "print('\\nSolver without batch norm:')\n",
    "solver = Solver(model, small_data,\n",
    "                num_epochs=10, batch_size=50,\n",
    "                update_rule='adam',\n",
    "                optim_config={\n",
    "                  'learning_rate': 1e-3,\n",
    "                },\n",
    "                verbose=True, print_every=20)\n",
    "solver.train()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Run the following to visualize the results from two networks trained above. You should find that using batch normalization helps the network to converge much faster."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "tags": [
     "pdf-ignore-input"
    ]
   },
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'solver' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mNameError\u001b[0m                                 Traceback (most recent call last)",
      "\u001b[1;32m<ipython-input-9-3bf20635fb65>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m\u001b[0m\n\u001b[0;32m     19\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m     20\u001b[0m \u001b[0mplt\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0msubplot\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;36m3\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;36m1\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;36m1\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 21\u001b[1;33m plot_training_history('Training loss','Iteration', solver, [bn_solver], \\\n\u001b[0m\u001b[0;32m     22\u001b[0m                       lambda x: x.loss_history, bl_marker='o', bn_marker='o')\n\u001b[0;32m     23\u001b[0m \u001b[0mplt\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0msubplot\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;36m3\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;36m1\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;36m2\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;31mNameError\u001b[0m: name 'solver' is not defined"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 720x576 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "def plot_training_history(title, label, baseline, bn_solvers, plot_fn, bl_marker='.', bn_marker='.', labels=None):\n",
    "    \"\"\"utility function for plotting training history\"\"\"\n",
    "    plt.title(title)\n",
    "    plt.xlabel(label)\n",
    "    bn_plots = [plot_fn(bn_solver) for bn_solver in bn_solvers]\n",
    "    bl_plot = plot_fn(baseline)\n",
    "    num_bn = len(bn_plots)\n",
    "    for i in range(num_bn):\n",
    "        label='with_norm'\n",
    "        if labels is not None:\n",
    "            label += str(labels[i])\n",
    "        plt.plot(bn_plots[i], bn_marker, label=label)\n",
    "    label='baseline'\n",
    "    if labels is not None:\n",
    "        label += str(labels[0])\n",
    "    plt.plot(bl_plot, bl_marker, label=label)\n",
    "    plt.legend(loc='lower center', ncol=num_bn+1) \n",
    "\n",
    "    \n",
    "plt.subplot(3, 1, 1)\n",
    "plot_training_history('Training loss','Iteration', solver, [bn_solver], \\\n",
    "                      lambda x: x.loss_history, bl_marker='o', bn_marker='o')\n",
    "plt.subplot(3, 1, 2)\n",
    "plot_training_history('Training accuracy','Epoch', solver, [bn_solver], \\\n",
    "                      lambda x: x.train_acc_history, bl_marker='-o', bn_marker='-o')\n",
    "plt.subplot(3, 1, 3)\n",
    "plot_training_history('Validation accuracy','Epoch', solver, [bn_solver], \\\n",
    "                      lambda x: x.val_acc_history, bl_marker='-o', bn_marker='-o')\n",
    "\n",
    "plt.gcf().set_size_inches(15, 15)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Batch normalization and initialization\n",
    "We will now run a small experiment to study the interaction of batch normalization and weight initialization.\n",
    "\n",
    "The first cell will train 8-layer networks both with and without batch normalization using different scales for weight initialization. The second layer will plot training accuracy, validation set accuracy, and training loss as a function of the weight initialization scale."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "tags": [
     "pdf-ignore-input"
    ]
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Running weight scale 1 / 20\n"
     ]
    },
    {
     "ename": "AttributeError",
     "evalue": "'NoneType' object has no attribute 'shape'",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mAttributeError\u001b[0m                            Traceback (most recent call last)",
      "\u001b[1;32m<ipython-input-10-44e66753f164>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m\u001b[0m\n\u001b[0;32m     25\u001b[0m                   },\n\u001b[0;32m     26\u001b[0m                   verbose=False, print_every=200)\n\u001b[1;32m---> 27\u001b[1;33m     \u001b[0mbn_solver\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mtrain\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m     28\u001b[0m     \u001b[0mbn_solvers_ws\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mweight_scale\u001b[0m\u001b[1;33m]\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mbn_solver\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m     29\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;32m~\\Desktop\\homework\\国创\\assignment2\\cs231n\\solver.py\u001b[0m in \u001b[0;36mtrain\u001b[1;34m(self)\u001b[0m\n\u001b[0;32m    283\u001b[0m             \u001b[0mlast_it\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mt\u001b[0m \u001b[1;33m==\u001b[0m \u001b[0mnum_iterations\u001b[0m \u001b[1;33m-\u001b[0m \u001b[1;36m1\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    284\u001b[0m             \u001b[1;32mif\u001b[0m \u001b[0mfirst_it\u001b[0m \u001b[1;32mor\u001b[0m \u001b[0mlast_it\u001b[0m \u001b[1;32mor\u001b[0m \u001b[0mepoch_end\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 285\u001b[1;33m                 train_acc = self.check_accuracy(\n\u001b[0m\u001b[0;32m    286\u001b[0m                     \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mX_train\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0my_train\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mnum_samples\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mnum_train_samples\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    287\u001b[0m                 )\n",
      "\u001b[1;32m~\\Desktop\\homework\\国创\\assignment2\\cs231n\\solver.py\u001b[0m in \u001b[0;36mcheck_accuracy\u001b[1;34m(self, X, y, num_samples, batch_size)\u001b[0m\n\u001b[0;32m    245\u001b[0m             \u001b[0mstart\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mi\u001b[0m \u001b[1;33m*\u001b[0m \u001b[0mbatch_size\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    246\u001b[0m             \u001b[0mend\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;33m(\u001b[0m\u001b[0mi\u001b[0m \u001b[1;33m+\u001b[0m \u001b[1;36m1\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;33m*\u001b[0m \u001b[0mbatch_size\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 247\u001b[1;33m             \u001b[0mscores\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mmodel\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mloss\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mX\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mstart\u001b[0m\u001b[1;33m:\u001b[0m\u001b[0mend\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m    248\u001b[0m             \u001b[0my_pred\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mnp\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0margmax\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mscores\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0maxis\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;36m1\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    249\u001b[0m         \u001b[0my_pred\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mnp\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mhstack\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0my_pred\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;32m~\\Desktop\\homework\\国创\\assignment2\\cs231n\\classifiers\\fc_net.py\u001b[0m in \u001b[0;36mloss\u001b[1;34m(self, X, y)\u001b[0m\n\u001b[0;32m    257\u001b[0m                     \u001b[0mgamma\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mparams\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;34m'gamma'\u001b[0m\u001b[1;33m+\u001b[0m\u001b[0mstrid\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    258\u001b[0m                     \u001b[0mbeta\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mparams\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;34m'beta'\u001b[0m\u001b[1;33m+\u001b[0m\u001b[0mstrid\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 259\u001b[1;33m                     \u001b[0mOutput\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mcache\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;34m'Cache'\u001b[0m \u001b[1;33m+\u001b[0m \u001b[0mstrid\u001b[0m\u001b[1;33m]\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0maffine_bn_relu_forward\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mInput\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mWi\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mbi\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mgamma\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mbeta\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mbn_params\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mi\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m    260\u001b[0m                 \u001b[1;32melif\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mnormalization\u001b[0m \u001b[1;33m==\u001b[0m \u001b[1;34m'layernorm'\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    261\u001b[0m                     \u001b[0mgamma\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mparams\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;34m'gamma'\u001b[0m\u001b[1;33m+\u001b[0m\u001b[0mstrid\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;32m~\\Desktop\\homework\\国创\\assignment2\\cs231n\\classifiers\\fc_net.py\u001b[0m in \u001b[0;36maffine_bn_relu_forward\u001b[1;34m(x, w, b, gamma, beta, bn_param)\u001b[0m\n\u001b[0;32m    324\u001b[0m \u001b[1;31m# affine + batch norm + relu的组合层前向\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    325\u001b[0m \u001b[1;32mdef\u001b[0m \u001b[0maffine_bn_relu_forward\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mx\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mw\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mb\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mgamma\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mbeta\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mbn_param\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 326\u001b[1;33m     \u001b[0ma\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mfc_cache\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0maffine_forward\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mx\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mw\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mb\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m    327\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    328\u001b[0m     \u001b[0mbn\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mbn_cache\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mbatchnorm_forward\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0ma\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mgamma\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mbeta\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mbn_param\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;32m~\\Desktop\\homework\\国创\\assignment2\\cs231n\\layers.py\u001b[0m in \u001b[0;36maffine_forward\u001b[1;34m(x, w, b)\u001b[0m\n\u001b[0;32m     24\u001b[0m     \u001b[1;31m###########################################################################\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m     25\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 26\u001b[1;33m     \u001b[0mN\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0mD\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mx\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mshape\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;36m0\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0mw\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mshape\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;36m0\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m     27\u001b[0m     \u001b[0mout\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mx\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mreshape\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mN\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0mD\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mdot\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mw\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;33m+\u001b[0m \u001b[0mb\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m     28\u001b[0m     \u001b[1;31m###########################################################################\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;31mAttributeError\u001b[0m: 'NoneType' object has no attribute 'shape'"
     ]
    }
   ],
   "source": [
    "np.random.seed(231)\n",
    "# Try training a very deep net with batchnorm\n",
    "hidden_dims = [50, 50, 50, 50, 50, 50, 50]\n",
    "num_train = 1000\n",
    "small_data = {\n",
    "  'X_train': data['X_train'][:num_train],\n",
    "  'y_train': data['y_train'][:num_train],\n",
    "  'X_val': data['X_val'],\n",
    "  'y_val': data['y_val'],\n",
    "}\n",
    "\n",
    "bn_solvers_ws = {}\n",
    "solvers_ws = {}\n",
    "weight_scales = np.logspace(-4, 0, num=20)\n",
    "for i, weight_scale in enumerate(weight_scales):\n",
    "    print('Running weight scale %d / %d' % (i + 1, len(weight_scales)))\n",
    "    bn_model = FullyConnectedNet(hidden_dims, weight_scale=weight_scale, normalization='batchnorm')\n",
    "    model = FullyConnectedNet(hidden_dims, weight_scale=weight_scale, normalization=None)\n",
    "\n",
    "    bn_solver = Solver(bn_model, small_data,\n",
    "                  num_epochs=10, batch_size=50,\n",
    "                  update_rule='adam',\n",
    "                  optim_config={\n",
    "                    'learning_rate': 1e-3,\n",
    "                  },\n",
    "                  verbose=False, print_every=200)\n",
    "    bn_solver.train()\n",
    "    bn_solvers_ws[weight_scale] = bn_solver\n",
    "\n",
    "    solver = Solver(model, small_data,\n",
    "                  num_epochs=10, batch_size=50,\n",
    "                  update_rule='adam',\n",
    "                  optim_config={\n",
    "                    'learning_rate': 1e-3,\n",
    "                  },\n",
    "                  verbose=False, print_every=200)\n",
    "    solver.train()\n",
    "    solvers_ws[weight_scale] = solver"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "tags": [
     "pdf-ignore-input"
    ]
   },
   "outputs": [
    {
     "ename": "KeyError",
     "evalue": "0.0001",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mKeyError\u001b[0m                                  Traceback (most recent call last)",
      "\u001b[1;32m<ipython-input-11-1ab7bc5e9ae8>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m\u001b[0m\n\u001b[0;32m      5\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m      6\u001b[0m \u001b[1;32mfor\u001b[0m \u001b[0mws\u001b[0m \u001b[1;32min\u001b[0m \u001b[0mweight_scales\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 7\u001b[1;33m   \u001b[0mbest_train_accs\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mmax\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0msolvers_ws\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mws\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mtrain_acc_history\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m      8\u001b[0m   \u001b[0mbn_best_train_accs\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mmax\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mbn_solvers_ws\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mws\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mtrain_acc_history\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m      9\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;31mKeyError\u001b[0m: 0.0001"
     ]
    }
   ],
   "source": [
    "# Plot results of weight scale experiment\n",
    "best_train_accs, bn_best_train_accs = [], []\n",
    "best_val_accs, bn_best_val_accs = [], []\n",
    "final_train_loss, bn_final_train_loss = [], []\n",
    "\n",
    "for ws in weight_scales:\n",
    "  best_train_accs.append(max(solvers_ws[ws].train_acc_history))\n",
    "  bn_best_train_accs.append(max(bn_solvers_ws[ws].train_acc_history))\n",
    "  \n",
    "  best_val_accs.append(max(solvers_ws[ws].val_acc_history))\n",
    "  bn_best_val_accs.append(max(bn_solvers_ws[ws].val_acc_history))\n",
    "  \n",
    "  final_train_loss.append(np.mean(solvers_ws[ws].loss_history[-100:]))\n",
    "  bn_final_train_loss.append(np.mean(bn_solvers_ws[ws].loss_history[-100:]))\n",
    "  \n",
    "plt.subplot(3, 1, 1)\n",
    "plt.title('Best val accuracy vs weight initialization scale')\n",
    "plt.xlabel('Weight initialization scale')\n",
    "plt.ylabel('Best val accuracy')\n",
    "plt.semilogx(weight_scales, best_val_accs, '-o', label='baseline')\n",
    "plt.semilogx(weight_scales, bn_best_val_accs, '-o', label='batchnorm')\n",
    "plt.legend(ncol=2, loc='lower right')\n",
    "\n",
    "plt.subplot(3, 1, 2)\n",
    "plt.title('Best train accuracy vs weight initialization scale')\n",
    "plt.xlabel('Weight initialization scale')\n",
    "plt.ylabel('Best training accuracy')\n",
    "plt.semilogx(weight_scales, best_train_accs, '-o', label='baseline')\n",
    "plt.semilogx(weight_scales, bn_best_train_accs, '-o', label='batchnorm')\n",
    "plt.legend()\n",
    "\n",
    "plt.subplot(3, 1, 3)\n",
    "plt.title('Final training loss vs weight initialization scale')\n",
    "plt.xlabel('Weight initialization scale')\n",
    "plt.ylabel('Final training loss')\n",
    "plt.semilogx(weight_scales, final_train_loss, '-o', label='baseline')\n",
    "plt.semilogx(weight_scales, bn_final_train_loss, '-o', label='batchnorm')\n",
    "plt.legend()\n",
    "plt.gca().set_ylim(1.0, 3.5)\n",
    "\n",
    "plt.gcf().set_size_inches(15, 15)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "tags": [
     "pdf-inline"
    ]
   },
   "source": [
    "## Inline Question 1:\n",
    "Describe the results of this experiment. How does the scale of weight initialization affect models with/without batch normalization differently, and why?\n",
    "\n",
    "## Answer:\n",
    "[FILL THIS IN]\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Batch normalization and batch size\n",
    "We will now run a small experiment to study the interaction of batch normalization and batch size.\n",
    "\n",
    "The first cell will train 6-layer networks both with and without batch normalization using different batch sizes. The second layer will plot training accuracy and validation set accuracy over time."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "tags": [
     "pdf-ignore-input"
    ]
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "No normalization: batch size =  5\n"
     ]
    },
    {
     "ename": "AttributeError",
     "evalue": "'NoneType' object has no attribute 'shape'",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mAttributeError\u001b[0m                            Traceback (most recent call last)",
      "\u001b[1;32m<ipython-input-12-a326e183e3ba>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m\u001b[0m\n\u001b[0;32m     45\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m     46\u001b[0m \u001b[0mbatch_sizes\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;33m[\u001b[0m\u001b[1;36m5\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;36m10\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;36m50\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 47\u001b[1;33m \u001b[0mbn_solvers_bsize\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0msolver_bsize\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mbatch_sizes\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mrun_batchsize_experiments\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'batchnorm'\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[1;32m<ipython-input-12-a326e183e3ba>\u001b[0m in \u001b[0;36mrun_batchsize_experiments\u001b[1;34m(normalization_mode)\u001b[0m\n\u001b[0;32m     25\u001b[0m                     },\n\u001b[0;32m     26\u001b[0m                     verbose=False)\n\u001b[1;32m---> 27\u001b[1;33m     \u001b[0msolver\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mtrain\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m     28\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m     29\u001b[0m     \u001b[0mbn_solvers\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;33m[\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;32m~\\Desktop\\homework\\国创\\assignment2\\cs231n\\solver.py\u001b[0m in \u001b[0;36mtrain\u001b[1;34m(self)\u001b[0m\n\u001b[0;32m    283\u001b[0m             \u001b[0mlast_it\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mt\u001b[0m \u001b[1;33m==\u001b[0m \u001b[0mnum_iterations\u001b[0m \u001b[1;33m-\u001b[0m \u001b[1;36m1\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    284\u001b[0m             \u001b[1;32mif\u001b[0m \u001b[0mfirst_it\u001b[0m \u001b[1;32mor\u001b[0m \u001b[0mlast_it\u001b[0m \u001b[1;32mor\u001b[0m \u001b[0mepoch_end\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 285\u001b[1;33m                 train_acc = self.check_accuracy(\n\u001b[0m\u001b[0;32m    286\u001b[0m                     \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mX_train\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0my_train\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mnum_samples\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mnum_train_samples\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    287\u001b[0m                 )\n",
      "\u001b[1;32m~\\Desktop\\homework\\国创\\assignment2\\cs231n\\solver.py\u001b[0m in \u001b[0;36mcheck_accuracy\u001b[1;34m(self, X, y, num_samples, batch_size)\u001b[0m\n\u001b[0;32m    245\u001b[0m             \u001b[0mstart\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mi\u001b[0m \u001b[1;33m*\u001b[0m \u001b[0mbatch_size\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    246\u001b[0m             \u001b[0mend\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;33m(\u001b[0m\u001b[0mi\u001b[0m \u001b[1;33m+\u001b[0m \u001b[1;36m1\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;33m*\u001b[0m \u001b[0mbatch_size\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 247\u001b[1;33m             \u001b[0mscores\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mmodel\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mloss\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mX\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mstart\u001b[0m\u001b[1;33m:\u001b[0m\u001b[0mend\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m    248\u001b[0m             \u001b[0my_pred\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mnp\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0margmax\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mscores\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0maxis\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;36m1\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    249\u001b[0m         \u001b[0my_pred\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mnp\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mhstack\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0my_pred\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;32m~\\Desktop\\homework\\国创\\assignment2\\cs231n\\classifiers\\fc_net.py\u001b[0m in \u001b[0;36mloss\u001b[1;34m(self, X, y)\u001b[0m\n\u001b[0;32m    263\u001b[0m                     \u001b[0mOutput\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mcache\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;34m'Cache'\u001b[0m \u001b[1;33m+\u001b[0m \u001b[0mstrid\u001b[0m\u001b[1;33m]\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0maffine_ln_relu_forward\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mInput\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mWi\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mbi\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mgamma\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mbeta\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mbn_params\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mi\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    264\u001b[0m                 \u001b[1;32melse\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 265\u001b[1;33m                     \u001b[0mOutput\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mcache\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;34m'Cache'\u001b[0m \u001b[1;33m+\u001b[0m \u001b[0mstrid\u001b[0m\u001b[1;33m]\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0maffine_relu_forward\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mInput\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mWi\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mbi\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m    266\u001b[0m                 \u001b[1;31m# drop out\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    267\u001b[0m                 \u001b[1;32mif\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0muse_dropout\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;32m~\\Desktop\\homework\\国创\\assignment2\\cs231n\\layer_utils.py\u001b[0m in \u001b[0;36maffine_relu_forward\u001b[1;34m(x, w, b)\u001b[0m\n\u001b[0;32m     21\u001b[0m     \u001b[1;33m-\u001b[0m \u001b[0mcache\u001b[0m\u001b[1;33m:\u001b[0m \u001b[0mObject\u001b[0m \u001b[0mto\u001b[0m \u001b[0mgive\u001b[0m \u001b[0mto\u001b[0m \u001b[0mthe\u001b[0m \u001b[0mbackward\u001b[0m \u001b[1;32mpass\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m     22\u001b[0m     \"\"\"\n\u001b[1;32m---> 23\u001b[1;33m     \u001b[0ma\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mfc_cache\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0maffine_forward\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mx\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mw\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mb\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m     24\u001b[0m     \u001b[0mout\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mrelu_cache\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mrelu_forward\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0ma\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m     25\u001b[0m     \u001b[0mcache\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;33m(\u001b[0m\u001b[0mfc_cache\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mrelu_cache\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;32m~\\Desktop\\homework\\国创\\assignment2\\cs231n\\layers.py\u001b[0m in \u001b[0;36maffine_forward\u001b[1;34m(x, w, b)\u001b[0m\n\u001b[0;32m     24\u001b[0m     \u001b[1;31m###########################################################################\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m     25\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 26\u001b[1;33m     \u001b[0mN\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0mD\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mx\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mshape\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;36m0\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0mw\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mshape\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;36m0\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m     27\u001b[0m     \u001b[0mout\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mx\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mreshape\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mN\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0mD\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mdot\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mw\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;33m+\u001b[0m \u001b[0mb\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m     28\u001b[0m     \u001b[1;31m###########################################################################\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;31mAttributeError\u001b[0m: 'NoneType' object has no attribute 'shape'"
     ]
    }
   ],
   "source": [
    "def run_batchsize_experiments(normalization_mode):\n",
    "    np.random.seed(231)\n",
    "    # Try training a very deep net with batchnorm\n",
    "    hidden_dims = [100, 100, 100, 100, 100]\n",
    "    num_train = 1000\n",
    "    small_data = {\n",
    "      'X_train': data['X_train'][:num_train],\n",
    "      'y_train': data['y_train'][:num_train],\n",
    "      'X_val': data['X_val'],\n",
    "      'y_val': data['y_val'],\n",
    "    }\n",
    "    n_epochs=10\n",
    "    weight_scale = 2e-2\n",
    "    batch_sizes = [5,10,50]\n",
    "    lr = 10**(-3.5)\n",
    "    solver_bsize = batch_sizes[0]\n",
    "\n",
    "    print('No normalization: batch size = ',solver_bsize)\n",
    "    model = FullyConnectedNet(hidden_dims, weight_scale=weight_scale, normalization=None)\n",
    "    solver = Solver(model, small_data,\n",
    "                    num_epochs=n_epochs, batch_size=solver_bsize,\n",
    "                    update_rule='adam',\n",
    "                    optim_config={\n",
    "                      'learning_rate': lr,\n",
    "                    },\n",
    "                    verbose=False)\n",
    "    solver.train()\n",
    "    \n",
    "    bn_solvers = []\n",
    "    for i in range(len(batch_sizes)):\n",
    "        b_size=batch_sizes[i]\n",
    "        print('Normalization: batch size = ',b_size)\n",
    "        bn_model = FullyConnectedNet(hidden_dims, weight_scale=weight_scale, normalization=normalization_mode)\n",
    "        bn_solver = Solver(bn_model, small_data,\n",
    "                        num_epochs=n_epochs, batch_size=b_size,\n",
    "                        update_rule='adam',\n",
    "                        optim_config={\n",
    "                          'learning_rate': lr,\n",
    "                        },\n",
    "                        verbose=False)\n",
    "        bn_solver.train()\n",
    "        bn_solvers.append(bn_solver)\n",
    "        \n",
    "    return bn_solvers, solver, batch_sizes\n",
    "\n",
    "batch_sizes = [5,10,50]\n",
    "bn_solvers_bsize, solver_bsize, batch_sizes = run_batchsize_experiments('batchnorm')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'solver_bsize' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mNameError\u001b[0m                                 Traceback (most recent call last)",
      "\u001b[1;32m<ipython-input-13-a97a72483031>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m\u001b[0m\n\u001b[0;32m      1\u001b[0m \u001b[0mplt\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0msubplot\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;36m2\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;36m1\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;36m1\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 2\u001b[1;33m plot_training_history('Training accuracy (Batch Normalization)','Epoch', solver_bsize, bn_solvers_bsize, \\\n\u001b[0m\u001b[0;32m      3\u001b[0m                       lambda x: x.train_acc_history, bl_marker='-^', bn_marker='-o', labels=batch_sizes)\n\u001b[0;32m      4\u001b[0m \u001b[0mplt\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0msubplot\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;36m2\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;36m1\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;36m2\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m      5\u001b[0m plot_training_history('Validation accuracy (Batch Normalization)','Epoch', solver_bsize, bn_solvers_bsize, \\\n",
      "\u001b[1;31mNameError\u001b[0m: name 'solver_bsize' is not defined"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 720x576 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.subplot(2, 1, 1)\n",
    "plot_training_history('Training accuracy (Batch Normalization)','Epoch', solver_bsize, bn_solvers_bsize, \\\n",
    "                      lambda x: x.train_acc_history, bl_marker='-^', bn_marker='-o', labels=batch_sizes)\n",
    "plt.subplot(2, 1, 2)\n",
    "plot_training_history('Validation accuracy (Batch Normalization)','Epoch', solver_bsize, bn_solvers_bsize, \\\n",
    "                      lambda x: x.val_acc_history, bl_marker='-^', bn_marker='-o', labels=batch_sizes)\n",
    "\n",
    "plt.gcf().set_size_inches(15, 10)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "tags": [
     "pdf-inline"
    ]
   },
   "source": [
    "## Inline Question 2:\n",
    "Describe the results of this experiment. What does this imply about the relationship between batch normalization and batch size? Why is this relationship observed?\n",
    "\n",
    "## Answer:\n",
    "[FILL THIS IN]\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Layer Normalization\n",
    "Batch normalization has proved to be effective in making networks easier to train, but the dependency on batch size makes it less useful in complex networks which have a cap on the input batch size due to hardware limitations. \n",
    "\n",
    "Several alternatives to batch normalization have been proposed to mitigate this problem; one such technique is Layer Normalization [2]. Instead of normalizing over the batch, we normalize over the features. In other words, when using Layer Normalization, each feature vector corresponding to a single datapoint is normalized based on the sum of all terms within that feature vector.\n",
    "\n",
    "[2] [Ba, Jimmy Lei, Jamie Ryan Kiros, and Geoffrey E. Hinton. \"Layer Normalization.\" stat 1050 (2016): 21.](https://arxiv.org/pdf/1607.06450.pdf)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "tags": [
     "pdf-inline"
    ]
   },
   "source": [
    "## Inline Question 3:\n",
    "Which of these data preprocessing steps is analogous to batch normalization, and which is analogous to layer normalization?\n",
    "\n",
    "1. Scaling each image in the dataset, so that the RGB channels for each row of pixels within an image sums up to 1.\n",
    "2. Scaling each image in the dataset, so that the RGB channels for all pixels within an image sums up to 1.  \n",
    "3. Subtracting the mean image of the dataset from each image in the dataset.\n",
    "4. Setting all RGB values to either 0 or 1 depending on a given threshold.\n",
    "\n",
    "## Answer:\n",
    "[FILL THIS IN]\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Layer Normalization: Implementation\n",
    "\n",
    "Now you'll implement layer normalization. This step should be relatively straightforward, as conceptually the implementation is almost identical to that of batch normalization. One significant difference though is that for layer normalization, we do not keep track of the moving moments, and the testing phase is identical to the training phase, where the mean and variance are directly calculated per datapoint.\n",
    "\n",
    "Here's what you need to do:\n",
    "\n",
    "* In `cs231n/layers.py`, implement the forward pass for layer normalization in the function `layernorm_forward`. \n",
    "\n",
    "Run the cell below to check your results.\n",
    "* In `cs231n/layers.py`, implement the backward pass for layer normalization in the function `layernorm_backward`. \n",
    "\n",
    "Run the second cell below to check your results.\n",
    "* Modify `cs231n/classifiers/fc_net.py` to add layer normalization to the `FullyConnectedNet`. When the `normalization` flag is set to `\"layernorm\"` in the constructor, you should insert a layer normalization layer before each ReLU nonlinearity. \n",
    "\n",
    "Run the third cell below to run the batch size experiment on layer normalization."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Check the training-time forward pass by checking means and variances\n",
    "# of features both before and after layer normalization   \n",
    "\n",
    "# Simulate the forward pass for a two-layer network\n",
    "np.random.seed(231)\n",
    "N, D1, D2, D3 =4, 50, 60, 3\n",
    "X = np.random.randn(N, D1)\n",
    "W1 = np.random.randn(D1, D2)\n",
    "W2 = np.random.randn(D2, D3)\n",
    "a = np.maximum(0, X.dot(W1)).dot(W2)\n",
    "\n",
    "print('Before layer normalization:')\n",
    "print_mean_std(a,axis=1)\n",
    "\n",
    "gamma = np.ones(D3)\n",
    "beta = np.zeros(D3)\n",
    "# Means should be close to zero and stds close to one\n",
    "print('After layer normalization (gamma=1, beta=0)')\n",
    "a_norm, _ = layernorm_forward(a, gamma, beta, {'mode': 'train'})\n",
    "print_mean_std(a_norm,axis=1)\n",
    "\n",
    "gamma = np.asarray([3.0,3.0,3.0])\n",
    "beta = np.asarray([5.0,5.0,5.0])\n",
    "# Now means should be close to beta and stds close to gamma\n",
    "print('After layer normalization (gamma=', gamma, ', beta=', beta, ')')\n",
    "a_norm, _ = layernorm_forward(a, gamma, beta, {'mode': 'train'})\n",
    "print_mean_std(a_norm,axis=1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Gradient check batchnorm backward pass\n",
    "np.random.seed(231)\n",
    "N, D = 4, 5\n",
    "x = 5 * np.random.randn(N, D) + 12\n",
    "gamma = np.random.randn(D)\n",
    "beta = np.random.randn(D)\n",
    "dout = np.random.randn(N, D)\n",
    "\n",
    "ln_param = {}\n",
    "fx = lambda x: layernorm_forward(x, gamma, beta, ln_param)[0]\n",
    "fg = lambda a: layernorm_forward(x, a, beta, ln_param)[0]\n",
    "fb = lambda b: layernorm_forward(x, gamma, b, ln_param)[0]\n",
    "\n",
    "dx_num = eval_numerical_gradient_array(fx, x, dout)\n",
    "da_num = eval_numerical_gradient_array(fg, gamma.copy(), dout)\n",
    "db_num = eval_numerical_gradient_array(fb, beta.copy(), dout)\n",
    "\n",
    "_, cache = layernorm_forward(x, gamma, beta, ln_param)\n",
    "dx, dgamma, dbeta = layernorm_backward(dout, cache)\n",
    "\n",
    "#You should expect to see relative errors between 1e-12 and 1e-8\n",
    "print('dx error: ', rel_error(dx_num, dx))\n",
    "print('dgamma error: ', rel_error(da_num, dgamma))\n",
    "print('dbeta error: ', rel_error(db_num, dbeta))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Layer Normalization and batch size\n",
    "\n",
    "We will now run the previous batch size experiment with layer normalization instead of batch normalization. Compared to the previous experiment, you should see a markedly smaller influence of batch size on the training history!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "ln_solvers_bsize, solver_bsize, batch_sizes = run_batchsize_experiments('layernorm')\n",
    "\n",
    "plt.subplot(2, 1, 1)\n",
    "plot_training_history('Training accuracy (Layer Normalization)','Epoch', solver_bsize, ln_solvers_bsize, \\\n",
    "                      lambda x: x.train_acc_history, bl_marker='-^', bn_marker='-o', labels=batch_sizes)\n",
    "plt.subplot(2, 1, 2)\n",
    "plot_training_history('Validation accuracy (Layer Normalization)','Epoch', solver_bsize, ln_solvers_bsize, \\\n",
    "                      lambda x: x.val_acc_history, bl_marker='-^', bn_marker='-o', labels=batch_sizes)\n",
    "\n",
    "plt.gcf().set_size_inches(15, 10)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "tags": [
     "pdf-inline"
    ]
   },
   "source": [
    "## Inline Question 4:\n",
    "When is layer normalization likely to not work well, and why?\n",
    "\n",
    "1. Using it in a very deep network\n",
    "2. Having a very small dimension of features\n",
    "3. Having a high regularization term\n",
    "\n",
    "\n",
    "## Answer:\n",
    "[FILL THIS IN]\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
